C#中对Oracle中Clob类型处理解析

您所在的位置:网站首页 oracle 解析clob里的xml C#中对Oracle中Clob类型处理解析

C#中对Oracle中Clob类型处理解析

2024-07-13 08:16:43| 来源: 网络整理| 查看: 265

  无

解决办法:

   无

 

方式3:采用参数形式,但是参数类型写为OracleType. NVarChar

代码:

string id = Guid.NewGuid().ToString(); OracleCommand cmd = Conn.CreateCommand(); cmd.CommandText = "insert into xx(id,test) values('" + id + "',:p1)"; OracleParameter p1 = new OracleParameter("p1", OracleType. NVarChar); p1.Value = data; // data是一个变量,存储你要插入的字符串  cmd.Parameters.Add(p1); cmd.ExecuteNonQuery();

情况分析:

    为什么要写这种方式,因为这种方式和采用NHibernate的方式很相似,先看看在这种方式会产生什么情况。 当data的字节数在0- 2000 之间时正常插入,大于4000时也正常插入,但在 2000 -4000时则失败,报错(ORA-01461:仅可以插入LONG列的LONG值赋值)

原因分析:

   没有采用对应的Oracle类型。

解决办法:

   采用OracleType.Clob

 

 

下边采用NHibernate插入数据,NHibernate具体怎用不在本次讨论范围。

NHibernate采用的版本为 1.2.1 .4000。

下边大至把简要配置写下。

 

App.config

 

   

 

 

   

   

   

    

   

   

   

 

 

xx.cs

using System; using System.Collections.Generic; using System.Text; namespace Test.Enties {     [Serializable]     public class Xx     {         public Xx()         {         }         private string id;         public virtual string Id         {             get { return id; }             set { id = value; }         }         public virtual string Test         {             get { return test; }             set { test = value; }         }         private string test;     } }

xx.hbm.xml

 

 

   

     

   

   

 

 

 

说明:

这里的驱动用的NHibernate.Driver.OracleClientDriver,其实是对微软的OracleClient的封装啦,其实内部还是调用微软的OracleClient的东东。引用System.Data.OracleClient.dll即可OracleClient。

 

做好上边的配置后,便有了以下的方式

方式4:采用NHibernate

代码:

string id = Guid.NewGuid().ToString(); Xx xx = new Xx(); xx.Test = data; // data是一个变量,存储你要插入的字符串 xx.Id = id; ISession session = SessionFactory.OpenSession(); session.Save(xx); session.Flush();

情况分析:

   当data的字节数在0- 2000 之间时正常插入,大于4000时也正常插入,但在 2000 -4000时则失败,报错(ORA-01461:仅可以插入LONG列的LONG值赋值).情况和方式3的情况一样。

原因分析:

   NHibernate在用OracleClient映射StringClob时,设置参数类型为OracleType. NVarChar,导致插入有BUG。网上有人推测是OracleClient的BUG所致,理由是换用OracleDataAccess即可解决。

 

为什么说NHibernate将参数类型设置为OracleType.NVarChar呢?看下边

 

找到NHibernate的源代码,把它加入你的工程。记得不要移动NHibernate位置直接加入工程,直接在NHibernate的安装目录引用进来。

 

 

   2. 在 Test 解决方案中添加NHibernate的项目引用。

经过上边两个步骤我们就可以跟踪调试NHibernate了

 

跟踪代码session.Save(xx);看看它究竟做了啥。

当我们跟进CommandSetBatchingBatcher时,可以得到以下信息(如图中的调试信息)。CurrentBatch类型是OracleClientCommandSet,OracleClientCommandSet看源码得知是对微软的OracleCommandSet的封装,因为这个类internal sealed class,所以我们的程序里是找不到这个类的,不过NHibernate通过反射使用了它的功能。OracleCommandSet可能用作批处理的,就是一次处理多个SQL语句的,不是太了解,谁知道请指教。

 

CommandSetBatchingBatcher的源码

internal class OracleClientCommandSet : DbCommandSet     {         private static System.Type oracleCmdSetType;         static OracleClientCommandSet()         {             Assembly sysDataOracleClient = Assembly.Load("System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");             oracleCmdSetType = sysDataOracleClient.GetType("System.Data.OracleClient.OracleCommandSet");             Debug.Assert(oracleCmdSetType != null, "Could not find OracleCommandSet!");         }         protected override object CreateInternalCommandSet()         {             return Activator.CreateInstance(oracleCmdSetType, true);         } }

跟踪CurrentBatch可以看到

CommandText:

declare

type refcursortype is ref cursor;

begin

INSERT INTO z3 ( test , id) VALUES (:p2, :p3);

:r1_4 := sql%rowcount;

end;

 

这里的p2就是我们的Clob类型字段的参数啦。

再看p2的OracleType是NVarChar,是不是有点明白啦,对了, 跟我们3一样,参数类型错掉了。

 

 

 

解决办法:

   使用NHibernate的自定义类型,不是太会,幸好网上有高人提供代码,在此想高人致谢。这样我们通过自定义类型来设置正确的OracleType即可。在项目中添加两个类。

   PatchForOracleLobField.cs

using System; using System.Collections.Generic; using System.Data; using System.Text; using NHibernate; using NHibernate.SqlTypes; using NHibernate.UserTypes; namespace Test.type {     public abstract class PatchForOracleLobField : IUserType     {         public PatchForOracleLobField()         {         }         public bool IsMutable         {             get { return true; }         }         public System.Type ReturnedType         {             get { return typeof(String); }         }         public SqlType[] SqlTypes         {             get             {                 return new SqlType[] { NHibernateUtil.String.SqlType };             }         }         public object DeepCopy(object value)         {             return value;         }         public new bool Equals(object x, object y)         {             return x == y;         }         public int GetHashCode(object x)         {             return x.GetHashCode();         }         public object Assemble(object cached, object owner)         {             return DeepCopy(cached);         }         public object Disassemble(object value)         {             return DeepCopy(value);         }         public object NullSafeGet(IDataReader rs, string[] names, object owner)         {             return NHibernate.NHibernateUtil.StringClob.NullSafeGet(rs, names[0]);         }         public abstract void NullSafeSet(IDbCommand cmd, object value, int index);         public object Replace(object original, object target, object owner)         {             return original;         }     } }

 

OracleClobField.cs

using System; using System.Collections.Generic; using System.Data; using System.Data.OracleClient; using System.Text; namespace Test.type {     public class OracleClobField : PatchForOracleLobField     {         public override void NullSafeSet(IDbCommand cmd, object value, int index)         {             if (cmd is OracleCommand)             {                 //CLob、NClob类型的字段,存入中文时参数的OracleDbType必须设置为OracleDbType.Clob                 //否则会变成乱码(Oracle 10g client环境)                 OracleParameter param = cmd.Parameters[index] as OracleParameter;                 if (param != null)                 {                     param.OracleType = OracleType.Clob;// 关键就这里啦                     param.IsNullable = true;                 }             }             NHibernate.NHibernateUtil.StringClob.NullSafeSet(cmd, value, index);         }     } }

 

然后在映射文件中修改类型即可。

Com.Dic.Icqs.Entities.Type.OracleClobField,Com.Dic.Icqs.Entities

修改前:

修改后:

Test .type.OracleClobField是类的完整名, Test 即OracleClobField所在的程序集。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭